package com.rfid.manager;

import static com.hoho.android.usbserial.util.SerialInputOutputManager.State.RUNNING;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import com.hoho.android.usbserial.driver.UsbId;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import com.rfid.a252robot.config.GlobalConfig;
import com.rfid.common.log.LogUtils;
import com.rfid.common.util.SharedPreferencesUtil;
import com.shrfid.module_base.entity.TagEntity;
import com.shrfid.module_base.util.ByteUtils;
import com.shrfid.rfidsdk.tag.NewReadTagManager;
import com.shrfid.rfidsdk.tag.RfidDecoder;
import com.shrfid.rfidsdk.tag.base.BaseDecoder;
import com.shrfid.rfidsdk.tag.hf.HFCommand;
import com.shrfid.rfidsdk.tag.hf.HFDecoder;
import com.shrfid.rfidsdk.tag.uhf.UHFCommand;
import com.shrfid.rfidsdk.tag.uhf.UHFDecoder;
import com.spectre.generate.ConfigManager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public enum  ReadTagManager {

    INSTANCE;

    private long scanTime;

    public static int INTERVAL_TIME = 1000;

    private final String TAG = "ReadTagDetectManager";

    private UsbSerialDriver sDriver;

    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();

    public RfidDecoder rfidDecoder = new RfidDecoder();

    private SerialInputOutputManager mSerialIoManager;

    private BaseDecoder baseDecoder;

    private UsbManager mUsbManager;

    private UsbDevice device;

    private ReadTagManager.IonDetectDeviceListener listener;

    private List<TagEntity> mTagEntities = new ArrayList<>();
    Handler handler = new Handler();
    Context mContext;
    //是否是超高频
    private boolean isUHF = false;

    private final SerialInputOutputManager.Listener mListener = new SerialInputOutputManager.Listener() {

        @Override
        public void onRunError(Exception e) {
            Log.d(TAG, "Runner stopped.");
//            handler.postDelayed(new Runnable() {
//                @Override
//                public void run() {
//                    prepareReadTag();
//                }
//            },3000);
        }

        @Override
        public void onNewData(final byte[] data) {
            try {
                if (baseDecoder != null) {
                    baseDecoder.decode(data);
                }
            } catch (Exception e) {
                LogUtils.e(e);
            }
        }
    };



    public void init(Context context, boolean isUHF, ReadTagManager.IonDetectDeviceListener listener) {
        mContext = context;
        this.listener = listener;
        this.isUHF = isUHF;
        mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        if (isUHF) {
            //超高频读写器
            baseDecoder = new UHFDecoder(new UHFCommand());
        } else {
            baseDecoder = new HFDecoder(new HFCommand());
        }
        findDevice();
    }

    public void findDevice() {
        for (final UsbDevice device : mUsbManager.getDeviceList().values()) {
            int vendorId = device.getVendorId();
            int productId = device.getProductId();
            String s = device.getSerialNumber();
            System.out.println(device.getProductName() + ":" + productId + ":" + vendorId);
            GlobalConfig config = ConfigManager.INSTANCE.getGlobalConfig();
            String ds = config.getTagReaderSerialNumber();
            if (productId == Integer.parseInt(config.getTagReaderPid(),16)&&vendorId == Integer.parseInt(config.getTagReaderVid(),16) ){
                if (!TextUtils.isEmpty(ds)) {
                    if (!ds.equals(s)) {
                        continue;
                    }
                }
                if (mUsbManager.hasPermission(device)) {
                    LogUtils.v("ReadTagManager init find device");
                    this.device = device;
                    break;
                } else {
                    requestPermission(device);
                    return;
                }
            }
        }
    }

    public void requestPermission(UsbDevice device) {
        UsbPermissionReceiver usbPermissionReceiver = new UsbPermissionReceiver();
        Intent intent = new Intent(UsbPermissionReceiver.ACTION_DEVICE_PERMISSION);
        PendingIntent mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
        IntentFilter permissionFilter = new IntentFilter(UsbPermissionReceiver.ACTION_DEVICE_PERMISSION);
        mContext.registerReceiver(usbPermissionReceiver, permissionFilter);
        mUsbManager.requestPermission(device, mPermissionIntent);
    }

    public boolean isConnect() {
        return device != null;
    }

    /**
     * 每次都重新打开，防止读不了的问题
     */
    public void prepareReadTag() {
        LogUtils.v("prepareReadTag");
        if (device == null) {
            findDevice();
        }
        if (device != null) {
            List<UsbSerialDriver> drivers = UsbSerialProber.probeSingleDevice(mUsbManager, device);
            if (drivers.isEmpty()) {
                findDevice();
                drivers = UsbSerialProber.probeSingleDevice(mUsbManager, device);
            }
            if (!drivers.isEmpty()) {
                sDriver = drivers.get(0);
                try {
                    sDriver.open();
                    try {
                        if (isUHF) {
                            sDriver.setParameters(115200, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE);
                        } else {
                            sDriver.setParameters(115200, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_ODD);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                startRead();
                setOnTagListener(new BaseDecoder.DecodeListener() {
                    @Override
                    public void onTagResult(List<TagEntity> data) {
                        if (data == null) {
                            return;
                        }
                        if (SharedPreferencesUtil.getInstance().getBoolean("show_tag")) {
                            LogViewManager.INSTANCE.add(data);
                        }
                        mTagEntities.addAll(data);
                    }
                });
            } else {
                LogUtils.v("ReadTagManager error! device cannot find driver!");
            }
        } else {
            LogUtils.v("ReadTagManager error! not found device");
        }
    }

    private void setOnTagListener(BaseDecoder.DecodeListener decodeListener) {
        if (baseDecoder != null) {
            baseDecoder.setListener(decodeListener);
        }
    }

    public void setReaderListener(BaseDecoder.ReaderListener readerListener) {
        if (baseDecoder != null) {
            baseDecoder.setReaderListener(readerListener);
        }
    }


    private void startRead() {
        LogUtils.v("reset IoManager");
        stopIoManager();
        startIoManager();
    }

    private void stopIoManager() {
        if (mSerialIoManager != null) {
            Log.i(TAG, "Stopping io manager ..");
            mSerialIoManager.stop();
            mSerialIoManager = null;
        }
    }

    private void startIoManager() {
        if (sDriver != null) {
            mSerialIoManager = new SerialInputOutputManager(sDriver, mListener);
            LogUtils.i(TAG, "Starting io manager .." + mSerialIoManager);
            mExecutor.submit(mSerialIoManager);
        }
    }


    /**
     * 同步读取标签,耗时操作
     *
     * @return 读取标签或者数据区数据
     */
    public List<TagEntity> readTags() {
        LogUtils.v("readTags");
        if (sDriver == null || mSerialIoManager == null || mSerialIoManager.getState() != RUNNING) {
            prepareReadTag();
        }
        List<TagEntity> tagEntities = new ArrayList<>();
        long now = System.currentTimeMillis();
        if (now - scanTime < 3000) {
            tagEntities.addAll(mTagEntities);
        }
        scanTime = now;
        mTagEntities.clear();
        try {
            LogUtils.v("write = " +ByteUtils.bytesToHexString(baseDecoder.inventory()));
            int result = sDriver.write(baseDecoder.inventory(), INTERVAL_TIME);
            LogUtils.v("result = " + result);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtils.v("readTags error " + e.getMessage());
        }
        int time = ConfigManager.INSTANCE.getGlobalConfig().getWaitTime();
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tagEntities.addAll(mTagEntities);
        LogUtils.v("readTags size = " + tagEntities.size());
        return mTagEntities;
    }

    public void selectAntenna(int antenna) {
        LogUtils.v("选择天线：" + antenna);
        try {
            if (sDriver == null || mSerialIoManager == null) {
                prepareReadTag();
            }
            int result = sDriver.write(baseDecoder.selectAntenna(antenna), INTERVAL_TIME);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 打开书籍的标记位(感应门会报警)
     */
    public void openFlag(String uidStr, String afi) {
        if (sDriver == null) {
            return;
        }
        try {
            byte[] uid = ByteUtils.hexString2Bytes(uidStr);
            if (afi != null) {
                if (afi.startsWith("0x")) {
                    int iAfi = Integer.parseInt(afi.substring(2), 16);
                    sDriver.write(baseDecoder.writeAfi(uid, (byte) iAfi), INTERVAL_TIME);
                }
            } else {
                sDriver.write(baseDecoder.writeAfi(uid, (byte) 0x07), INTERVAL_TIME);
            }
            Thread.sleep(50);
            sDriver.write(baseDecoder.setEas(uid), INTERVAL_TIME);
            Thread.sleep(50);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭书籍的标记位(感应不门会报警)
     */
    public void closeFlag(String uidStr) {
        if (sDriver == null) {
            return;
        }
        try {
            byte[] uid = ByteUtils.hexString2Bytes(uidStr);
            sDriver.write(baseDecoder.writeAfi(uid, (byte) 0xC2), INTERVAL_TIME);
            Thread.sleep(50);
            sDriver.write(baseDecoder.resetEas(uid), INTERVAL_TIME);
            Thread.sleep(50);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void close() {
        if (sDriver == null) {
            return;
        }
        try {
            stopIoManager();
            if (sDriver != null) {
                sDriver.close();
                sDriver = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public interface IonDetectDeviceListener {
        void detectComplete();
    }
}
